/**
 * @file Setup.cpp
 * @author Michael Fetisov (fetisov.michael@bmstu.ru)
 * @brief 
 * @version 0.1
 * @date 2022-08-26
 * 
 * @copyright Copyright (c) 2022
 * 
 */

#include "simodo/setup/SetupJsonBuilder.h"
#include "simodo/setup/SetupStructure.h"
#include "simodo/variable/json/Serialization.h"
#include "simodo/inout/convert/functions.h"

namespace simodo::setup
{
    SetupDescription SetupJsonBuilder::build(const std::string & setup_file) 
    {
        SetupDescription    res;
        variable::Value     value;

        _errors = variable::loadJson(setup_file, value);

        if (!_errors.empty())
            return res;

        if (value.type() != variable::ValueType::Object) {
            /// \todo Тут и далее поменять на более понятное описание ошибки
            _errors = "Недопустимый формат #1";
            return res;
        }

        std::shared_ptr<variable::Object> setup_object = value.getObject();

        const variable::Value & brief_value       = setup_object->find(u"brief");
        const variable::Value & description_value = setup_object->find(u"description");
        const variable::Value & setup_value       = setup_object->find(u"setup");

        /// \todo Разделить проверки с подробным описанием
        if (brief_value.type() != variable::ValueType::String
         || description_value.type() != variable::ValueType::String
         || setup_value.type() != variable::ValueType::Array) {
            _errors = "Недопустимый формат #2";
            return res;
        }

        res.brief       = inout::toU8(brief_value.getString());
        res.description = inout::toU8(description_value.getString());

        std::shared_ptr<variable::Array> setup_array = setup_value.getArray();

        for(const variable::Value & v : setup_array->values()) {
            if (v.type() != variable::ValueType::Object) {
                _errors = "Недопустимый формат #3";
                return res;
            }

            std::shared_ptr<variable::Object> param_object = v.getObject();

            const variable::Value & param_id_value          = param_object->find(u"id");
            const variable::Value & param_name_value        = param_object->find(u"name");
            const variable::Value & param_brief_value       = param_object->find(u"brief");
            const variable::Value & param_description_value = param_object->find(u"description");
            const variable::Value & param_value             = param_object->find(u"value");

            /// \todo Разделить проверки с подробным описанием
            if (param_id_value.type() != variable::ValueType::String
             || param_name_value.type() != variable::ValueType::String
             || param_brief_value.type() != variable::ValueType::String
             || param_description_value.type() != variable::ValueType::String) {
                _errors = "Недопустимый формат #4";
                return res;
            }

            SetupStructure param_struct;            

            param_struct.id             = inout::toU8(param_id_value.getString());
            param_struct.name           = inout::toU8(param_name_value.getString());
            param_struct.brief          = inout::toU8(param_brief_value.getString());
            param_struct.description    = inout::toU8(param_description_value.getString());
            param_struct.value          = param_value;

            res.setup.push_back(param_struct);
        }

        return res;
    }
}
